package org.jeecg.board.service.impl;/**
 * @Description
 * @Author LiCY
 * @Date 2023/4/24
 */

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.board.dto.BoardDataDTO;
import org.jeecg.board.dto.LineAndonBoardDTO;
import org.jeecg.board.dto.LineBoardBarDTO;
import org.jeecg.board.mapper.LineBoardMapper;
import org.jeecg.board.mapper.PlantBoardMapper;
import org.jeecg.board.service.PlantBoardService;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 功能描述：
 *
 * @author: LCY
 * @date: 2023年04月24日 14:01
 */
@Service
@Slf4j
public class PlantBoardServiceImpl implements PlantBoardService {
    @Autowired
    private PlantBoardMapper plantBoardMapper;

    @Autowired
    private LineBoardMapper lineBoardMapper;

    @Autowired
    public RedisTemplate redisTemplate;

    @Autowired
    private CommonAPI commonAPI;


    @Override
    public Result<Map<String, Object>> getPlantBoardData(Map<String, Object> param) {
//        String key = "plantBoardData";
//        Map<String, Object> data = (Map<String, Object>) redisTemplate.opsForValue().get(key);
        //获取车间看板数据
        Map<String, Object> map = new HashMap<>();
        //1.获取成品工序生产总数
        Integer packTotal =plantBoardMapper.getPlantParamTotal(param,"packTotal");
        map.put("packTotal",packTotal);
        //2.获取计划生产总数
        Integer woPlanTotal =plantBoardMapper.getPlantParamTotal(param,"woPlanTotal");
        map.put("woPlanTotal",woPlanTotal);
        //3.获取报废总数
        Integer monthScrapTotal =plantBoardMapper.getPlantParamTotal(param,"monthScrapList");
        map.put("monthScrapTotal",monthScrapTotal);
        //4.获取月度产出列表
        List<BoardDataDTO> monthPackList  =plantBoardMapper.getPlantParamList(param,"packTotal");
        map.put("monthPackList",monthPackList);
        //5.获取月度报废列表
        List<BoardDataDTO> monthScrapList  =plantBoardMapper.getPlantParamList(param,"monthScrapList");
        map.put("monthScrapList",monthScrapList);
        //6.获取月度产出趋势图
        List<LineBoardBarDTO> yearPackList  =plantBoardMapper.getPlantPackList(param);
        map.put("yearPackList",yearPackList);
        //7.获取当月产出型号分布
        List<BoardDataDTO> monthPackPartNoList  =plantBoardMapper.getPlantPartNoList(param);
        map.put("monthPackPartNoList",monthPackPartNoList);
        //8.获取当年总产出
        Integer yearPackTotal  = plantBoardMapper.getPlantYearTotal();
        map.put("yearPackTotal",yearPackTotal);
        //9.获取时间稼动率
        map.put("availability",91.45);
        //10.获取FTQ
        map.put("quality", 96.21);
        //11.获取性能稼动率
        map.put("performance",95.72);
        //12.获取当月OEE
        map.put("curOee",84.22);
        //13.获取上月OEE
        map.put("preOee", 85.72);
        //14.获取环比OEE
        map.put("preYearOee",82.36);
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 获取当前年月
        String currentYearMonth = formatDate(currentDate);

        // 获取前一个月的日期
        LocalDate previousMonthDate = currentDate.minusMonths(1);
        String previousMonth = formatDate(previousMonthDate);

        // 获取前一年的日期
        LocalDate previousYearDate = currentDate.minusYears(1);
        String previousYear = formatDate(previousYearDate);

        map.put("currentYearMonth",currentYearMonth);
        map.put("previousMonth",previousMonth);
        map.put("previousYear",previousYear);
        log.info("从redis获取车间看板数据");
        return Result.OK(map);
    }

    @Override
    public Map<String, Object> incorporationData(Map<String, Object> a1, Map<String, Object> a2,boolean isTrue) {
        Integer packTotal = (Integer) a2.get("packTotal");
        Integer packTotal1 = (Integer) a1.get("packTotal");
        a1.put("packTotal",packTotal+packTotal1);
        Integer woPlanTotal = (Integer) a2.get("woPlanTotal");
        Integer woPlanTotal1 = (Integer) a1.get("woPlanTotal");
        a1.put("woPlanTotal",woPlanTotal+woPlanTotal1);
        List<BoardDataDTO> monthScrapList = (List<BoardDataDTO>) a2.get("monthScrapList");
        List<BoardDataDTO> monthScrapList1 = (List<BoardDataDTO>) a1.get("monthScrapList");
        monthScrapList1.addAll(monthScrapList);
        a1.put("monthScrapList",monthScrapList1);
        Integer monthScrapTotal = (Integer) a2.get("monthScrapTotal");
        Integer monthScrapTotal1 = (Integer) a1.get("monthScrapTotal");
        a1.put("monthScrapTotal",monthScrapTotal+monthScrapTotal1);
        if (isTrue){
            redisTemplate.opsForValue().set("plantBoardData", a1, 2, TimeUnit.DAYS);
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("master");
        }
        return a1;
    }

    @Override
    public Map<String, Object> getPlantBoardProductionData(Map<String, Object> map) {
        return null;
        //redisTemplate.opsForValue().set("plantBoardData", map, 2, TimeUnit.DAYS);
    }

    /**
     * 将日期格式化为 YYYYMM 格式
     *
     * @param date 要格式化的日期
     * @return 格式化后的字符串
     */
    private static String formatDate(LocalDate date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
        return date.format(formatter);
    }

    @Override
    public Result<Map<String, Object>> geQisLineBoardData(Map<String, Object> param) {
        String line = "";
        if (param.containsKey("line")){
            line = (String) param.get("line");
        }
        String key = "qisLineBoardData"+"-"+line;
        Map<String, Object> data = (Map<String, Object>) redisTemplate.opsForValue().get(key);
        log.info("从redis获取看板数据");
        return Result.OK(data);
    }


    public Result<List<LineAndonBoardDTO>> getPlantAndonBoardData2(List<String> list) {
        List<LineAndonBoardDTO> lineAndonBoardDTOS = new ArrayList<>();
        String lines = "C8_SEED";
        String standByLines = "C84";
        //遍历产线列表获取安灯报警数据
        list.forEach(item->{
            //切换数据源
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("H"+item);
            //获取产线安灯报警数据
            //1.获取理论当天生产时间
            //获取当日开班时间
            Integer dayStartTime = lineBoardMapper.getDayStartTime();
            //获取当前时间 判断当前时间如果小于开班时间则日期减一
            LocalDateTime now1 = LocalDateTime.now();
            LocalDateTime STime;
            int hour = now1.getHour();
            if (dayStartTime>hour){
                //日期减一
                STime = LocalDateTime.of(now1.minusDays(1).toLocalDate(), LocalTime.of(dayStartTime, 0));
            }else{
                STime = LocalDateTime.of(now1.toLocalDate(), LocalTime.of(dayStartTime, 0));
            }
            LineAndonBoardDTO lineAndonBoardDTO = new LineAndonBoardDTO();
            DecimalFormat decimalFormat = new DecimalFormat("#0.00");
            int opNum = lineBoardMapper.getOpNum();
            Double theoreticalProductionTime = plantBoardMapper.getTheoreticalProductionTime(STime.toString());
            //2.获取理论小时生产时间
            //获取小时开始时间
            LocalDateTime startOfHour = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS);
            Double theoreticalProductionHour = plantBoardMapper.getTheoreticalProductionTime(startOfHour.toString());
            //3.获取实际当天生产时间
            Double dayAvailability =  plantBoardMapper.getLineAvailability(STime.toString());
            //4.获取实际小时生产时间
            //Double hourAvailability =  plantBoardMapper.getLineAvailability(startOfHour.toString());
            //5.获取当天瓶颈停机时间
            Double dayDowntime = plantBoardMapper.getLineBottleneckDowntime(STime.toString());
            lineAndonBoardDTO.setLine(item);
            if (lines.contains(item)){
                lineAndonBoardDTO.setBekido("100");
                lineAndonBoardDTO.setBekidoH("0.00");
            }else {
                double v = theoreticalProductionTime * opNum;
                double v1 = theoreticalProductionHour * opNum;
                lineAndonBoardDTO.setBekido(decimalFormat.format(dayAvailability/v*100));
                //lineAndonBoardDTO.setBekidoH(decimalFormat.format(hourAvailability/v1*100));
                lineAndonBoardDTO.setBekidoH(decimalFormat.format(dayDowntime));
            }
            //5.获取当前产线状态
            int isWarn = 0;
            int warn1 = plantBoardMapper.getMachinestate();
            int warn2 = plantBoardMapper.getAndonstate();
            isWarn=warn1>0?warn1:warn2;
            if (isWarn>0){
                lineAndonBoardDTO.setStatus("WARN");
                lineAndonBoardDTO.setTimes(isWarn);
            }else{
                lineAndonBoardDTO.setStatus("RUNNING");
            }
            if (lineAndonBoardDTO.getBekido().contains("0.0")){
                lineAndonBoardDTO.setStatus("StandBy");
            }
            lineAndonBoardDTOS.add(lineAndonBoardDTO);
        });
        return Result.OK(lineAndonBoardDTOS);
    }

    @Override
    public Result<List<LineAndonBoardDTO>> getPlantAndonBoardData(List<String> list) {
        List<LineAndonBoardDTO> lineAndonBoardDTOS = new ArrayList<>();
        String lines = "C8_SEED";
        //遍历产线列表获取安灯报警数据
        list.forEach(item->{
            //切换数据源
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("H"+item);
            Map<String, Object> param = new HashMap<>();
            LineAndonBoardDTO lineAndonBoardDTO = new LineAndonBoardDTO();
            //获取当日开班时间
            Integer dayStartTime = lineBoardMapper.getDayStartTime();
            String lineName = lineBoardMapper.getLineName();
            //获取当前时间 判断当前时间如果小于开班时间则日期减一
            LocalDateTime now1 = LocalDateTime.now();
            LocalDateTime STime;
            int hour = now1.getHour();
            if (dayStartTime>hour){
                //日期减一
                STime = LocalDateTime.of(now1.minusDays(1).toLocalDate(), LocalTime.of(dayStartTime, 0));
            }else{
                STime = LocalDateTime.of(now1.toLocalDate(), LocalTime.of(dayStartTime, 0));
            }
            param.put("line",item);
            param.put("start",STime);
            param.put("end",now1);
            //获取当天OEE
            //获取节拍
            String nowPartNo = lineBoardMapper.getNowPartNo();
            param.put("currentPartNo", nowPartNo);
            Integer beat = lineBoardMapper.getCtNum(param);
            if (beat == null) {
                beat = 60;
            }
            //获取完工工位
            String fGOpName = lineBoardMapper.getFgOp(param);
            param.put("fGOpName", fGOpName);
            String lineOee = getLineOee(param, beat);
            lineAndonBoardDTO.setLine(lineName);
            lineAndonBoardDTO.setBekido(lineOee);
            //获取前一小时OEE
            //获取前一个小时的开始时间与结束时间
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();
            // 计算前一个小时的开始时间（精确到小时）
            LocalDateTime start = now.truncatedTo(ChronoUnit.HOURS).minusHours(1);
            // 计算前一个小时的结束时间（精确到秒）
            LocalDateTime end = start.plusHours(1).minusSeconds(1);
            // 格式化输出（包含日期）
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            param.put("start",start);
            param.put("end",end);
            String lineOee2 = getLineOee(param, beat);
            lineAndonBoardDTO.setBekidoH(lineOee2);
            //5.获取当前产线状态
            int isWarn = 0;
            int warn1 = plantBoardMapper.getMachinestate();
            int warn2 = plantBoardMapper.getAndonstate();
            isWarn=warn1>0?warn1:warn2;
            if (isWarn>0){
                lineAndonBoardDTO.setStatus("WARN");
                lineAndonBoardDTO.setTimes(isWarn);
            }else{
                lineAndonBoardDTO.setStatus("RUNNING");
            }
            if (lineOee.equals("0")&&!lines.contains(item)){
                lineAndonBoardDTO.setStatus("StandBy");
            }
            if (lines.contains(item)){
                lineAndonBoardDTO.setBekido("100");
                lineAndonBoardDTO.setBekidoH("100");
            }
            lineAndonBoardDTOS.add(lineAndonBoardDTO);
        });
        return Result.OK(lineAndonBoardDTOS);
    }

    private String getLineOee(Map<String, Object> param, Integer beat){
        DecimalFormat decimalFormat = new DecimalFormat("#0");
        Double availability =  lineBoardMapper.getLineAvailability(param);
        Double performance =  lineBoardMapper.getLinePerformance(param);
        Double todayDowntime = lineBoardMapper.getTodayDowntime2(param);
        Double todayQualifiedNum = lineBoardMapper.getTodayQualifiedNum(param);
        Double todayUnqualifiedNum = lineBoardMapper.getTodayUnqualifiedNum(param);
        int opNum = lineBoardMapper.getOpNum();
        double tcr = availability/(todayDowntime*opNum);
        double pr = performance/(todayDowntime/beat);
        double ftq = 0.0;
        ftq = todayQualifiedNum / (todayQualifiedNum + todayUnqualifiedNum);
        if (Double.isNaN(ftq)){
            ftq=0.0;
        }
        if (todayQualifiedNum==0.0){
            ftq=0.0;
        }
        if (tcr==0.0||tcr>1.0){
            tcr=1.0;
        }
        if (pr==0.0||pr>1.0){
            pr=1.0;
        }
        double oee = Math.round(tcr * pr * ftq * 100);
        if (oee<0){
            oee=0;
        }
        if (oee>100){
            oee=100;
        }
        return decimalFormat.format(oee);
    }

}
